package com.hunttown.mes.manage.controller._erp;

import com.hunttown.mes.common.OperateCode;
import com.hunttown.mes.manage.controller.common.AdminBaseClass;
import com.hunttown.mes.manage.controller.common.ModelService;
import com.hunttown.mes.rpc.domain.AnalysisManageDTO;
import com.hunttown.mes.rpc.domain.TransportPurchaseInventoryDTO;
import com.hunttown.mes.rpc.domain.TransportPurchaseInventoryDetailDTO;
import com.hunttown.mes.rpc.domain.query.TransportPurchaseInventoryDTOQuery;
import com.hunttown.mes.rpc.domain.query.TransportPurchaseInventoryDetailDTOQuery;
import com.hunttown.common.domain.Page;
import com.hunttown.mes.common.utils.*;
import com.hunttown.mes.manage.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

import static com.hunttown.mes.common.utils.PageUtils.PagePackage;

/**
 * @title: 采销盘点
 * @author: wangjunfu
 * @date: 2019-12-24 15:51:58
 * @description:
 */
@Controller
@RequestMapping(value = "/erp/inventory")
public class PurchaseInventoryController {

    private final static Logger logger = LoggerFactory.getLogger(PurchaseInventoryController.class);

    private final TransportPurchaseInventoryManageService inventoryService;
    private final AnalysisManageManageService manageService;
    private final TransportPurchaseInventoryDetailManageService inventoryDetailService;
    private final ModelService modelService;
    private final TransactionService transactionService;
    private final TransportOperateLogManageService logService;

    @Autowired
    public PurchaseInventoryController(TransportPurchaseInventoryManageService inventoryService, AnalysisManageManageService manageService, TransportPurchaseInventoryDetailManageService inventoryDetailService, ModelService modelService, TransactionService transactionService, TransportOperateLogManageService logService) {
        this.inventoryService = inventoryService;
        this.manageService = manageService;
        this.inventoryDetailService = inventoryDetailService;
        this.modelService = modelService;
        this.transactionService = transactionService;
        this.logService = logService;
    }

    //region 数据列表

    /**
     * 首页
     *
     * @param model    model模型
     * @param dtoQuery 查询条件
     * @return
     */
    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index(Model model, TransportPurchaseInventoryDTOQuery dtoQuery) {

        //region 显示标题
        String showTitle = "未知";
        if (dtoQuery.getPurchaseType() == 1) {
            showTitle = "配件";
        }
        if (dtoQuery.getPurchaseType() == 2) {
            showTitle = "物料";
        }
        model.addAttribute("showTitle", showTitle);
        //endregion

        dtoQuery.setOrderBy("order by id desc");
        Page<TransportPurchaseInventoryDTO> dataPage = inventoryService.getForPage(dtoQuery);

        for (TransportPurchaseInventoryDTO item : dataPage.getItems()) {
            item.setInventoryCn(modelService.getManageName(item.getInventory()));
            item.setReviewerCn(modelService.getManageName(item.getReviewer()));
        }

        model.addAttribute("page", dataPage);
        model.addAttribute("PagePackage", PagePackage(dataPage.getPn(), dataPage.getStart(), dataPage.getPageSize(), dataPage.getTotalPages(), dataPage.getTotalItems()));
        model.addAttribute("dtoQuery", dtoQuery);

        return "erp/inventory/index";
    }
    //endregion

    //region 编辑&保存

    /**
     * 编辑
     *
     * @param model model模型
     * @param id    主键id
     * @return
     */
    @RequestMapping(value = "/edit", method = RequestMethod.GET)
    public String edit(Model model, Integer id, Integer purchaseType) {
        id = (id == null ? 0 : id);

        TransportPurchaseInventoryDTO obj = new TransportPurchaseInventoryDTO();
        obj.setId(id);
        obj.setPurchaseType(purchaseType);

        if (id > 0) {
            obj = inventoryService.getById(id);
            purchaseType = obj.getPurchaseType();

            //1.获取盘点明细
            TransportPurchaseInventoryDetailDTOQuery detailDTOQuery = new TransportPurchaseInventoryDetailDTOQuery();
            detailDTOQuery.setInventoryId(id);
            detailDTOQuery.setStopFlag(0);
            detailDTOQuery.setPageSize(1000);
            Page<TransportPurchaseInventoryDetailDTO> dataPage = inventoryDetailService.getForPage(detailDTOQuery);
            for (TransportPurchaseInventoryDetailDTO item : dataPage.getItems()) {
                item.setInventoryCn(modelService.getManageName(item.getInventory()));
                item.setPartName(modelService.getPurchaseName(item.getPartId()));
            }
            model.addAttribute("page", dataPage);

        } else {

            //1.获取盘点明细
            TransportPurchaseInventoryDetailDTOQuery detailDTOQuery = new TransportPurchaseInventoryDetailDTOQuery();
            Calendar calendar = Calendar.getInstance();
            detailDTOQuery.setPurchaseType(purchaseType);
            detailDTOQuery.setInventoryId(0);   //表示未生成过盘点单
            detailDTOQuery.setpYear(calendar.get(Calendar.YEAR));
            detailDTOQuery.setpMonth(calendar.get(Calendar.MONTH) + 1);
            detailDTOQuery.setPageSize(1000);   //最大只能获取1000条
            detailDTOQuery.setStopFlag(0);
            Page<TransportPurchaseInventoryDetailDTO> dataPage = inventoryDetailService.getForPage(detailDTOQuery);

            List<Integer> effectiveIds = new ArrayList<>();
            for (TransportPurchaseInventoryDetailDTO item : dataPage.getItems()) {
                item.setInventoryCn(modelService.getManageName(item.getInventory()));
                item.setPartName(modelService.getPurchaseName(item.getPartId()));
                obj.setInventory(item.getInventory());
                obj.setInventoryDate(item.getInventoryDate());
                effectiveIds.add(item.getId());
            }

            model.addAttribute("page", dataPage);

            String preTitle = "未知";
            if (purchaseType == 1) {
                preTitle = "配件";
            }
            if (purchaseType == 2) {
                preTitle = "物料";
            }

            obj.setTotalCount(Integer.valueOf(dataPage.getTotalItems() + ""));
            obj.setInventoryName(String.format("%s%s盘点单", preTitle, DateConvertUtils.dateToYearMonth(new Date())));
            obj.setPartidsArray(StringUtils.join(effectiveIds.toArray(), ","));
        }

        model.addAttribute("Obj", obj);

        modelService.getManagerPage(model);

        //region 显示标题
        String showTitle = "未知";
        if (purchaseType == 1) {
            showTitle = "配件";
        }
        if (purchaseType == 2) {
            showTitle = "物料";
        }
        model.addAttribute("showTitle", showTitle);
        //endregion

        return "erp/inventory/edit";
    }

    /**
     * 保存 ajax异步
     *
     * @param request sevelet请求
     * @param objDTO  实体类
     * @return
     */
    @RequestMapping(value = "/saveEdit", method = RequestMethod.POST)
    @ResponseBody
    public String saveEditNotify(HttpServletRequest request, TransportPurchaseInventoryDTO objDTO) {

        // 结果返回 结果至少包含一个操作状态和一条状态信息
        String result = "";
        Map<String, String> map = new HashMap<String, String>();

        try {

            //判断盘点人和复核人
            if (objDTO.getInventory() == 0 || objDTO.getReviewer() == 0) {
                map = OperateCode.CompositionResult(map, -10, "请选择盘点人和复核人！");
                result = JSONUtils.toJSON(map);
                return result;
            }

            if (Objects.equals(objDTO.getInventory(), objDTO.getReviewer())) {
                map = OperateCode.CompositionResult(map, -10, "盘点人和复核人不能相同！");
                result = JSONUtils.toJSON(map);
                return result;
            }

            String pin = AdminBaseClass.getPin(request);
            AnalysisManageDTO curr_obj = manageService.getFromCachePin(pin);

            if (objDTO.getId() == null || objDTO.getId() <= 0) {
                //新增
                //检查是否有盘点明细
                List<Integer> idList = FormatUtils.commaToList_Integer(objDTO.getPartidsArray());
                if (idList.size() == 0) {
                    map = OperateCode.CompositionResult(map, -10, "没有查询到盘点明细，无法生成盘点单！");
                    result = JSONUtils.toJSON(map);
                    return result;
                }

                //region 1. 伪事务 - 新增
                //设置初始值
                Calendar calendar = Calendar.getInstance();

                objDTO.setInventoryNo(GeneralUtils.GenTimeSeries(4, null, null));
                objDTO.setAdminId(curr_obj.getId());
                objDTO.setCreateTime(new Date());
                objDTO.setTotalCount(idList.size());
                objDTO.setpYear(calendar.get(Calendar.YEAR));
                objDTO.setpMonth(calendar.get(Calendar.MONTH) + 1);
                objDTO.setInventoryDate(DateConvertUtils.strToDate(objDTO.getInventoryDateSr()));
                objDTO.setReviewDate(objDTO.getInventoryDate());
                objDTO.setApplyId(0);
                objDTO.setStatus(0);
                objDTO.setStopFlag(0);
                objDTO.setDeleteFlag(0);
                objDTO = inventoryService.insert(objDTO);

                if (objDTO == null || objDTO.getId() <= 0) {
                    //操作失败
                    map = OperateCode.CompositionResult(map, -1);
                    result = JSONUtils.toJSON(map);
                    return result;
                }
                //endregion

                //region 2. 伪事务 - 操作成功保存明细中的盘点ID
                TransportPurchaseInventoryDetailDTOQuery detailDTOQuery = new TransportPurchaseInventoryDetailDTOQuery();
                detailDTOQuery.setInventoryId(objDTO.getId());
                detailDTOQuery.setW_pYear(calendar.get(Calendar.YEAR));
                detailDTOQuery.setW_pMonth(calendar.get(Calendar.MONTH) + 1);
                detailDTOQuery.setIds(idList);
                Boolean isNext = inventoryDetailService.updateInfoByQuery(detailDTOQuery);
                if (!isNext) {
                    //取消盘点单
                    inventoryService.changeState(objDTO.getId(), 1);

                    //程序终止，返回失败信息
                    map = OperateCode.CompositionResult(map, -1);
                    result = JSONUtils.toJSON(map);
                    return result;
                }
                //eneregion

                //region 3. 伪事务 - 生成审批流程
                Map<String, String> param = new HashMap<>();
                param.put("applyTitle", objDTO.getInventoryName());

                //[改版后]审批人走的是会员系统
                param.put("firstExector", modelService.getUserIdByAdminId(objDTO.getInventory()) + "");
                param.put("secondExector", modelService.getUserIdByAdminId(objDTO.getReviewer()) + "");

                Integer applyId = transactionService.createApplyWithout("purchase_inventory", "transport_purchase_inventory", objDTO.getId(), objDTO.getAdminId(), param);
                if (applyId > 0) {

                    //（1）更新盘点单表中的applyid
                    TransportPurchaseInventoryDTO updateDto = new TransportPurchaseInventoryDTO();
                    updateDto.setId(objDTO.getId());
                    updateDto.setApplyId(applyId);
                    inventoryService.updateInfoById(updateDto);

                    //（2）根据applyId 获取第一个流程环节
                    // 自动走完第一个环节
                    transactionService.autoApplyFirstNode(applyId, 1, curr_obj.getId());

                } else {
                    // 调用一次“撤消”结账单方法
                    cancleCheckout(request, objDTO.getId(), curr_obj.getId());

                    //程序终止，返回失败信息
                    map = OperateCode.CompositionResult(map, -1);
                    result = JSONUtils.toJSON(map);
                    return result;
                }
                //endregion

            } else {
                //更新
                //将不需要更新的字段设置为NULL
                Boolean isNext = inventoryService.updateInfoById(objDTO);

                if (!isNext) {
                    //操作失败
                    map = OperateCode.CompositionResult(map, -1);
                    result = JSONUtils.toJSON(map);
                    return result;
                }
            }

            //region *** 更新信息完毕记录操作日志 ***
            logService.insertSimple(1, 90, objDTO.getId(), 2,
                    "更新盘点信息",
                    FastJsonUtils.toJSONString(objDTO),
                    curr_obj.getId(),
                    IpUtils.getClientIp(request),
                    SystemUtils.getBrowserInfo(request));
            //endregion

            //操作成功 结果返回
            map = OperateCode.CompositionResult(map, 1);
            result = JSONUtils.toJSON(map);
            return result;

        } catch (Exception e) {
            //清空map
            map.clear();
            map = OperateCode.CompositionResult(map, -1);
            result = JSONUtils.toJSON(map);
            return result;
        }
    }
    //endregion

    //region 删除&改变状态

    /**
     * 通过id删除 ajax异步
     *
     * @param id 记录id
     * @return
     */
    @RequestMapping(value = "/deleteById", method = RequestMethod.POST)
    @ResponseBody
    public String deleteNotify(HttpServletRequest request, Integer id) {

        // 结果返回结果至少包含一个操作状态和一条状态信息
        String result = "";
        Map<String, String> map = new HashMap<String, String>();

        if (id == null || id <= 0) {
            map = OperateCode.CompositionResult(map, -10, "请选择要删除的记录！");
            result = JSONUtils.toJSON(map);
            return result;
        }

        try {
            Boolean isNext = inventoryService.delete(id);

            //region *** 更新信息完毕记录操作日志 ***
            String pin = AdminBaseClass.getPin(request);
            AnalysisManageDTO curr_obj = manageService.getFromCachePin(pin);
            logService.insertSimple(1, 90, id, 4,
                    "删除盘点信息",
                    "记录删除：" + (isNext ? "成功" : "失败") + "：" + id,
                    curr_obj.getId(),
                    IpUtils.getClientIp(request),
                    SystemUtils.getBrowserInfo(request));
            //endregion

            map = OperateCode.CompositionResult(map, isNext ? 1 : 0);
            result = JSONUtils.toJSON(map);
            return result;

        } catch (Exception e) {
            //清空map
            map.clear();
            map = OperateCode.CompositionResult(map, -1);
            result = JSONUtils.toJSON(map);
            return result;
        }
    }

    /**
     * 状态改变 ajax异步
     *
     * @param id     记录id
     * @param status 状态
     * @return
     */
    @RequestMapping(value = "/changeFlag", method = RequestMethod.POST)
    @ResponseBody
    public String openOrStopFlag(HttpServletRequest request, Integer id, Integer status) {

        // 结果返回 结果至少包含一个操作状态和一条状态信息
        String result = "";
        Map<String, String> map = new HashMap<String, String>();

        try {
            Boolean isNext = inventoryService.changeState(id, status);

            //region *** 更新信息完毕记录操作日志 ***
            String pin = AdminBaseClass.getPin(request);
            AnalysisManageDTO curr_obj = manageService.getFromCachePin(pin);
            logService.insertSimple(1, 90, id == null ? 0 : id, 2,
                    "更新盘点状态",
                    "记录状态更新" + (isNext ? "成功" : "失败") + "：" + id,
                    curr_obj.getId(),
                    IpUtils.getClientIp(request),
                    SystemUtils.getBrowserInfo(request));
            //endregion

            map = OperateCode.CompositionResult(map, isNext ? 1 : 0);
            result = JSONUtils.toJSON(map);
            return result;

        } catch (Exception e) {
            //清空map
            map.clear();
            map = OperateCode.CompositionResult(map, -1);
            result = JSONUtils.toJSON(map);
            return result;
        }
    }

    //endregion

    //region "撤消"盘点单

    /**
     * 撤消盘点单
     *
     * @param id 盘点单id
     * @return true or false
     */
    private Boolean cancleCheckout(HttpServletRequest request, Integer id, Integer adminId) {
        if (id == null || id <= 0) {
            return false;
        }

        //1. 取消盘点单状态
        Boolean isNext = inventoryService.changeState(id, 1);

        //2. 将盘点明细的inventory_id 去掉
        if (isNext) {
            TransportPurchaseInventoryDTO dto = inventoryService.getById(id);
            if (dto != null) {

                TransportPurchaseInventoryDetailDTOQuery updateQuery = new TransportPurchaseInventoryDetailDTOQuery();
                updateQuery.setInventoryId(0);
                updateQuery.setW_inventoryId(id);
                inventoryDetailService.updateInfoByQuery(updateQuery);

                //3. 撤消审批
                if (dto.getApplyId() > 0) {
                    // 根据 applyid 获取最新审批环节
                    // 自动走完当前审批环节（调用一次审批方法）
                    transactionService.autoApplyCurrNode(dto.getApplyId(), -10, adminId);
                }

                //region *** 更新信息完毕记录操作日志 ***
                String pin = AdminBaseClass.getPin(request);
                AnalysisManageDTO curr_obj = manageService.getFromCachePin(pin);
                logService.insertSimple(1, 90, id == null ? 0 : id, 2,
                        "撤消盘点单",
                        "记录状态更新" + (isNext ? "成功" : "失败") + "：" + id,
                        curr_obj.getId(),
                        IpUtils.getClientIp(request),
                        SystemUtils.getBrowserInfo(request));
                //endregion
            }
        }

        return isNext;
    }
    //endregion
}